const express = require('express');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const router = express.Router();

const db = require('../database/connection');

// Generate unique referral code
function generateReferralCode() {
  return crypto.randomBytes(16).toString('hex');
}

// Register user with wallet
router.post('/register', async (req, res) => {
  try {
    const { walletAddress, password, referralCode } = req.body;

    if (!walletAddress || !password) {
      return res.status(400).json({ error: 'Wallet address and password are required' });
    }

    // Validate wallet address format
    if (!/^0x[a-fA-F0-9]{40}$/.test(walletAddress)) {
      return res.status(400).json({ error: 'Invalid wallet address format' });
    }

    // Check if user already exists
    const existingUser = await db.query(
      'SELECT id FROM users WHERE wallet_address = ?',
      [walletAddress.toLowerCase()]
    );

    if (existingUser.length > 0) {
      return res.status(409).json({ error: 'User with this wallet address already exists' });
    }

    // Validate referral code if provided
    let referredBy = null;
    if (referralCode) {
      const referrer = await db.query(
        'SELECT id FROM users WHERE referral_code = ?',
        [referralCode]
      );

      if (referrer.length === 0) {
        return res.status(400).json({ error: 'Invalid referral code' });
      }

      referredBy = referrerCode;
    }

    // Hash password
    const saltRounds = 12;
    const passwordHash = await bcrypt.hash(password, saltRounds);

    // Generate unique referral code
    let newReferralCode = generateReferralCode();
    let referralExists = true;

    while (referralExists) {
      const existing = await db.query(
        'SELECT id FROM users WHERE referral_code = ?',
        [newReferralCode]
      );
      if (existing.length === 0) {
        referralExists = false;
      } else {
        newReferralCode = generateReferralCode();
      }
    }

    // Create user and initial balance in a transaction
    const result = await db.transaction(async (connection) => {
      // Insert user
      const [userResult] = await connection.execute(
        `INSERT INTO users (wallet_address, password_hash, referral_code, referred_by)
         VALUES (?, ?, ?, ?)`,
        [walletAddress.toLowerCase(), passwordHash, newReferralCode, referredBy]
      );

      const userId = userResult.insertId;

      // Create initial balance record
      await connection.execute(
        'INSERT INTO user_balances (user_id) VALUES (?)',
        [userId]
      );

      return { userId, referralCode: newReferralCode };
    });

    // Generate JWT token
    const token = jwt.sign(
      { userId: result.userId, walletAddress },
      process.env.JWT_SECRET,
      { expiresIn: process.env.JWT_EXPIRES_IN || '7d' }
    );

    res.status(201).json({
      message: 'User registered successfully',
      token,
      referralCode: result.referralCode
    });

  } catch (error) {
    console.error('Registration error:', error);
    res.status(500).json({ error: 'Registration failed' });
  }
});

// Login user
router.post('/login', async (req, res) => {
  try {
    const { walletAddress, password } = req.body;

    if (!walletAddress || !password) {
      return res.status(400).json({ error: 'Wallet address and password are required' });
    }

    // Find user
    const users = await db.query(
      'SELECT id, wallet_address, password_hash FROM users WHERE wallet_address = ?',
      [walletAddress.toLowerCase()]
    );

    if (users.length === 0) {
      return res.status(401).json({ error: 'Invalid credentials' });
    }

    const user = users[0];

    // Verify password
    const isValidPassword = await bcrypt.compare(password, user.password_hash);

    if (!isValidPassword) {
      return res.status(401).json({ error: 'Invalid credentials' });
    }

    // Generate JWT token
    const token = jwt.sign(
      { userId: user.id, walletAddress: user.wallet_address },
      process.env.JWT_SECRET,
      { expiresIn: process.env.JWT_EXPIRES_IN || '7d' }
    );

    res.json({
      message: 'Login successful',
      token,
      user: {
        id: user.id,
        walletAddress: user.wallet_address
      }
    });

  } catch (error) {
    console.error('Login error:', error);
    res.status(500).json({ error: 'Login failed' });
  }
});

// Verify token middleware
function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];

  if (!token) {
    return res.status(401).json({ error: 'Access token required' });
  }

  jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
    if (err) {
      return res.status(403).json({ error: 'Invalid or expired token' });
    }
    req.user = user;
    next();
  });
}

module.exports = { router, authenticateToken };